﻿#include <iostream>
#include <condition_variable>
#include <queue>
#include <future>
#include "Base.h"
#include "MyException.h"



//使用condition_variable时，必须确保在等待之前获取互斥锁，并且在唤醒后释放互斥锁。
//wait、wait_for和wait_until函数都会释放互斥锁，然后在等待期间重新获取它。
//notify_one唤醒一个等待的线程，而notify_all唤醒所有等待的线程。

std::mutex mtx;
std::condition_variable cv;
std::queue<int> product;

void producer(int id) {
	for (int i = 0; i < 5; ++i) 
	{
		std::unique_lock<std::mutex> lck(mtx);
		product.push(id * 100 + i);
		std::cout << "Producer " << id << " produced " << product.back() << std::endl;
		cv.notify_one();
		lck.unlock();
		std::this_thread::sleep_for(std::chrono::milliseconds(100));
	}
}

void consumer(int id) 
{
	while (true) {
		std::unique_lock<std::mutex> lck(mtx);
		cv.wait(lck, [] { return !product.empty(); });
		if (!product.empty()) {
			int prod = product.front();
			product.pop();
			std::cout << "Consumer " << id << " consumed " << prod << std::endl;
		}
		lck.unlock();
	}
}



std::atomic<int> counter(0); // 初始化原子计数器

void increment() 
{
	for (int i = 0; i < 10000; ++i) {
		counter.fetch_add(1, std::memory_order_relaxed); // 原子增加
	}
}


int main()
{
	std::thread producers[2];
	std::thread consumers[2];

	for (int i = 0; i < 2; ++i)
	{
		producers[i] = std::thread(producer, i + 1);
	}

	for (int i = 0; i < 2; ++i)
	{
		consumers[i] = std::thread(consumer, i + 1);
	}

	for (int i = 0; i < 2; ++i)
	{
		producers[i].join();
	}






	/*<atomic> 库，它提供了一组原子操作，用于保证在多线程环境下对单个数据的访问
	是原子的，即不可分割的。这可以避免数据竞争和保证线程安全。*/
	std::thread t1(increment);
	std::thread t2(increment);

	t1.join();
	t2.join();

	std::cout << "Final counter value: " << counter << std::endl; // 输出最终的计数器值





	//<type_traits> 是 C++ 标准库中一个非常有用的头文件，它包含了一组编译时检查类型特性的工具
	std::cout << "int is integral: " << std::is_integral<int>::value << std::endl;
	std::cout << "float is integral: " << std::is_integral<float>::value << std::endl;
	std::cout << "char is integral: " << std::is_integral<char>::value << std::endl;


	//<typeinfo> 是标准库的一部分，它提供了运行时类型识别（RTTI，Run-Time Type Identification）功能
	Base* basePtr = new Derived();
	Base* basePtr2 = new Base();

	std::cout << "Type of basePtr: " << typeid(*basePtr).name() << std::endl;
	std::cout << "Type of basePtr2: " << typeid(*basePtr2).name() << std::endl;

	if (typeid(*basePtr) == typeid(Derived)) {
		std::cout << "basePtr is of type Derived" << std::endl;
	}
	else {
		std::cout << "basePtr is not of type Derived" << std::endl;
	}

	delete basePtr;
	delete basePtr2;



	//异常处理
	try {
		// 模拟一个错误情况
		bool error_condition = true;
		if (error_condition) {
			throw MyException();
		}
	}
	catch (const std::exception& e) {
		std::cout << "Caught an exception: " << e.what() << std::endl;
	}
}
